//
//  circlelist.c
//  循环链表的设计与实现
//
//  Created by ZJ on 2018/7/13.
//  Copyright © 2018年 iCatch Technology Inc. All rights reserved.
//

#include "circlelist.h"
#include <stdlib.h>

typedef struct _tag_CircleList {
    CircleListNode header;
    CircleListNode* slider;
    int length;
}TCircleList;

CircleList* CircleList_Create(void)
{
    TCircleList *ret = (TCircleList *)malloc(sizeof(TCircleList));
    if (ret == NULL) {
        printf("func CircleList_Create() error.\n");
        return NULL;
    }
    
    ret->length = 0;
    ret->header.next = NULL;
    ret->slider = NULL;
    
    return ret;
}

void CircleList_Destroy(CircleList *list)
{
    if (list != NULL) {
        free(list);
        list = NULL;
    }
}

void CircleList_Clear(CircleList *list)
{
    TCircleList *tList = (TCircleList *)list;
    if (tList == NULL) {
        printf("func CircleList_Clear() error: list is NULL.");
        return;
    }
    
    tList->length = 0;
    tList->header.next = NULL;
    tList->slider = NULL;
}

int CircleList_Length(CircleList *list)
{
    TCircleList *tList = (TCircleList *)list;
    int ret = -1;
    if (tList == NULL) {
        printf("func CircleList_Length() error: list is NULL.");

        return ret;
    }
    
    ret = tList->length;
    return ret;
}

int CircleList_Insert(CircleList *list, CircleListNode *node, int pos)
{
    TCircleList *tList = (TCircleList *)list;
    
    if (tList == NULL || node == NULL || pos < 0) {
        printf("func CircleList_Insert() error: list is NULL or node is NULL or pos < 0");

        return -1;
    }
    
    // 当pos大于链表长度时修正pos的值（对于循环链表可以不进行修正）
    if (pos > CircleList_Length(tList)) {
        pos = CircleList_Length(tList);
    }
    
    CircleListNode *current = (CircleListNode *)tList;
    
    for (int i = 0; (i < pos) && (current->next != NULL); i++) {
        current = current->next;
    }
    
    node->next = current->next;
    current->next = node;
    
    if (tList->length == 0) {
        tList->slider = node;
    }
    
    tList->length ++;
    
    // 当在 0 号位置插入 node 时要确保最后元素的next域指向第一个元素
    if (current == (CircleListNode *)tList) {
        CircleListNode* last = Circle_Get(tList, tList->length - 1);
        last->next = current->next;
    }
    
    return 0;
}


CircleListNode* Circle_Get(CircleList* list, int pos)
{
    TCircleList *tList = (TCircleList *)list;
    
    if (tList == NULL || pos < 0) {
        printf("func Circle_Get() error: list is NULL or pos < 0.");
        return NULL;
    }
    
    CircleListNode *current = (CircleListNode *)tList;
    
    for (int i = 0; (i < pos) && (current->next != NULL); i++) {
        current = current->next;
    }
    
    return current->next;
}

CircleListNode* Circle_Delete(CircleList *list, int pos)
{
    TCircleList *tList = (TCircleList *)list;
    
    if (tList == NULL || pos < 0) {
        printf("func Circle_Delete() error: list is NULL or pos < 0.");
        return NULL;
    }
    
    CircleListNode *ret = NULL;
    CircleListNode *current = (CircleListNode *)tList;
    
    for (int i = 0; (i < pos) && (current->next != NULL); i++) {
        current = current->next;
    }
    
    ret = current->next;
    current->next = ret->next;
    
    tList->length --;
    
    // 当删除第一个node时要特殊处理
    if (current == (CircleListNode *)tList && tList->length > 0) {
        CircleListNode *last = Circle_Get(tList, tList->length - 1);
        last->next = current->next;
    }
    
    // 当删除的元素为游标元素时，让游标后移
    if (tList->slider == ret) {
        tList->slider = ret->next;
    }
    
    return ret;
}

// add

CircleListNode* CircleList_DeleteNode(CircleList *list, CircleListNode *node)
{
    TCircleList *tList = (TCircleList *)list;
    
    if (tList == NULL || node == NULL) {
        printf("func Circle_Delete() error: list is NULL or node is NULL.");
        return NULL;
    }
    
    CircleListNode *current = (CircleListNode *)tList;
    
    for (int i = 0; i < CircleList_Length(tList); i++) {
        if (node == current->next) {
            current->next = node->next;
            tList->length--;
            
            if (current == (CircleListNode *)tList) {
                CircleListNode *last = Circle_Get(tList, tList->length - 1);
                last->next = current->next;
            }
            
            if (tList->slider == node) {
                tList->slider = node->next;
            }
            
            return node;
        }
        
        current = current->next;
    }
    
    return NULL;
}

CircleListNode* CircleList_Reset(CircleList *list)
{
    CircleList_Clear(list);
    
    return NULL;
}

CircleListNode* CircleList_Current(CircleList *list)
{
    TCircleList *tList = (TCircleList *)list;
    
    if (tList == NULL) {
        printf("func CircleList_Current() error: list is NULL.");
        return NULL;
    }
    
    return tList->slider;
}

CircleListNode* CircleList_Next(CircleList *list)
{
    TCircleList *tList = (TCircleList *)list;
    
    if (tList == NULL) {
        printf("func CircleList_Current() error: list is NULL.");
        return NULL;
    }
    
    tList->slider = tList->slider->next;
    
    return tList->slider;
}
